package com.xinruke.hostels.reservation.user.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xinruke.hostels.cache.extract.extractor.DictInfoCacheExtractor;
import com.xinruke.hostels.common.cache.ReservationUserCache;
import com.xinruke.hostels.common.constants.RedisConstants;
import com.xinruke.hostels.common.constants.SysDicConstant;
import com.xinruke.hostels.common.exception.BizException;
import com.xinruke.hostels.common.mybatis.MyExample;
import com.xinruke.hostels.common.po.MhHuiyuan;
import com.xinruke.hostels.common.po.MhHuiyuanQinshu;
import com.xinruke.hostels.common.util.CustomSecurity;
import com.xinruke.hostels.common.util.EmptyUtil;
import com.xinruke.hostels.common.util.UUIDUtil;
import com.xinruke.hostels.common.vo.ErrorEnum;
import com.xinruke.hostels.common.vo.ResultVO;
import com.xinruke.hostels.common.vo.query.EConditionOperator;
import com.xinruke.hostels.common.vo.query.QueryConditions;
import com.xinruke.hostels.common.vo.query.RowsDataVO;
import com.xinruke.hostels.reservation.interfaces.api.ReservationApi;
import com.xinruke.hostels.reservation.interfaces.dto.DiscountsRemainingQueryDTO;
import com.xinruke.hostels.reservation.user.interfaces.dto.*;
import com.xinruke.hostels.reservation.user.mapper.MhHuiyuanMapper;
import com.xinruke.hostels.reservation.user.mapper.MhHuiyuanQinshuMapper;
import com.xinruke.hostels.reservation.user.service.LoginService;
import com.xinruke.hostels.reservation.user.service.MemberService;
import com.xinruke.hostels.reservation.user.service.PersonalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;
import tk.mybatis.mapper.weekend.Weekend;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xinruke.hostels.common.util.CustomSecurity.encodeMobile;


/**
 * 会员管理
 *
 * @author Jinz
 * @date 2019-06-30 11:50
 */
@Slf4j
@Service
public class MemberServiceImpl implements MemberService {

    @Autowired
    private MhHuiyuanMapper mhHuiyuanMapper;

    @Resource
    private MhHuiyuanQinshuMapper mhHuiyuanQinshuMapper;

    @Autowired
    private LoginService loginService;

    @Resource
    private PersonalService personalService;

    @Resource
    private ReservationApi reservationApi;

    @Autowired
    private DictInfoCacheExtractor dictInfoCacheExtractor;

    @Autowired
    private ReservationUserCache reservationUserCache;

    @Resource(name = "commonRedisTemplate")
    private RedisTemplate commonRedisTemplate;

    /**
     * 会员详情查看
     *
     * @param memberDetailQuertDTO
     * @return com.xinruke.hostels.common.vo.ResultVO<com.xinruke.hostels.reservation.user.interfaces.dto.MemberDetailQuertResultDTO>
     * @author Jinz
     * @date 2019-06-30 13:11
     */
    @Override
    public ResultVO<MemberDetailQuertResultDTO> detail(MemberDetailQuertDTO memberDetailQuertDTO) {
        ResultVO<MemberDetailQuertResultDTO> result = ResultVO.success();
//        String account = memberDetailQuertDTO.getShenfenzhenghao();
//        account = CustomSecurity.encodeIDCard(account);
//
//        QueryConditions andConditions = new QueryConditions();
//        andConditions.addCondition("shenfenzhenghao", EConditionOperator.EQULS, account);
//        MyExample myExample = new MyExample(MhHuiyuan.class, andConditions);
//        MhHuiyuan member = mhHuiyuanMapper.selectOneByExample(myExample);

        if (reservationUserCache == null) {
            return new ResultVO(ErrorEnum.ERROR_211.getCode(), ErrorEnum.ERROR_211.getMsg());
        }
        MhHuiyuan member = reservationUserCache.getLoginReservationUserInfo();
        if (EmptyUtil.isEmpty(member)) {
            return ResultVO.fail("无此身份证号");
        }
        MemberDetailQuertResultDTO memberDetailQuertResultDTO = new MemberDetailQuertResultDTO();
        BeanUtils.copyProperties(member, memberDetailQuertResultDTO);
        result.setData(memberDetailQuertResultDTO);
        return result;
    }

    /**
     * 会员密码修改
     *
     * @param memberPassWordUpdateDTO
     * @return com.xinruke.hostels.common.vo.ResultVO
     * @author Jinz
     * @date 2019-06-30 13:11
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO update(MemberPassWordUpdateDTO memberPassWordUpdateDTO) {
        try {
            MhHuiyuan member = reservationUserCache.getLoginReservationUserInfo();
            //会员密码校验
            String password = CustomSecurity.createUserPassword(member.getShenfenzhenghao(), member.getYan(), memberPassWordUpdateDTO.getOldPwd());
            if (!password.equals(member.getMima())) {
                return new ResultVO(ErrorEnum.ERROR_21012.getCode(), ErrorEnum.ERROR_21012.getMsg());
            }

            //修改密码
            member.setYan(UUIDUtil.getUUID());
            String newPwd = CustomSecurity.createUserPassword(member.getShenfenzhenghao(), member.getYan(), memberPassWordUpdateDTO.getNewPwd());
            member.setMima(newPwd);
            member.setGengxinshijian(new Date());
            int check = mhHuiyuanMapper.updateByPrimaryKeySelective(member);
            if (check <= 0) {
                return new ResultVO(ErrorEnum.ERROR_21013.getCode(), ErrorEnum.ERROR_21013.getMsg());
            }

            //退出当前登录
            loginService.userLoginOut();
        } catch (Exception e) {
            log.error("会员密码修改异常，", e);
            return new ResultVO(ErrorEnum.ERROR_21013.getCode(), ErrorEnum.ERROR_21013.getMsg());
        }
        return ResultVO.success();
    }

    @Override
    public ResultVO<RowsDataVO<MemberDetailQuertResultDTO>> getMemberList(MemberListQueryDTO memberListQueryDTO) {
        ResultVO<RowsDataVO<MemberDetailQuertResultDTO>> resultVO = ResultVO.success();

        memberListQueryDTO.setShoujihao(CustomSecurity.encodeMobile(memberListQueryDTO.getShoujihao()));
        memberListQueryDTO.setShenfenzhenghao(CustomSecurity.encodeIDCard(memberListQueryDTO.getShenfenzhenghao()));

        QueryConditions andQueryConditions = new QueryConditions();

        andQueryConditions.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
        andQueryConditions.addCondition("xingming", EConditionOperator.LIKE, memberListQueryDTO.getXingming());
        andQueryConditions.addCondition("shoujihao", EConditionOperator.LIKE, memberListQueryDTO.getShoujihao());
        andQueryConditions.addCondition("shenfenzhenghao", EConditionOperator.LIKE, memberListQueryDTO.getShenfenzhenghao());
        andQueryConditions.addCondition("zhuangtai", EConditionOperator.EQULS, memberListQueryDTO.getZhuangtai());
        andQueryConditions.addCondition("dadanwei", EConditionOperator.EQULS, memberListQueryDTO.getDadanwei());
        andQueryConditions.addCondition("zhijiedaiyu", EConditionOperator.EQULS, memberListQueryDTO.getZhijiedaiyu());

        MyExample myExample = new MyExample(MhHuiyuan.class, andQueryConditions, memberListQueryDTO.getOrderFields());

        Page<MhHuiyuan> page = PageHelper.startPage(memberListQueryDTO.getPageNo(), memberListQueryDTO.getPageSize());
        List<MhHuiyuan> mhHuiyuans = mhHuiyuanMapper.selectByExample(myExample);

        List<MemberDetailQuertResultDTO> memberList = mhHuiyuans.stream().map(e -> {

            MemberDetailQuertResultDTO memberDetailQuertResultDTO = new MemberDetailQuertResultDTO();
            BeanUtils.copyProperties(e, memberDetailQuertResultDTO);

            memberDetailQuertResultDTO.setShengyuyouhuicishu(getDiscounts(e.getId()));
            memberDetailQuertResultDTO.setDadanweiMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.DADANWEI, e.getDadanwei()));
            memberDetailQuertResultDTO.setZhijidaiyuMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.ZHIJIDAIYU, e.getZhijiedaiyu()));
            memberDetailQuertResultDTO.setZhuangtaiMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.ZHUANGTAI, e.getZhuangtai()));

            return memberDetailQuertResultDTO;
        }).collect(Collectors.toList());

        RowsDataVO<MemberDetailQuertResultDTO> vo = new RowsDataVO<>();
        vo.setPageNo(page.getPageNum());
        vo.setRows(memberList);
        vo.setTotalPages(page.getPages());
        vo.setTotalRecords(page.getTotal());

        resultVO.setData(vo);

        return resultVO;
    }

    @Override
    public ResultVO<MemberDetailQuertResultDTO> detailById(MemberDetailQueryByIdDTO memberDetailQueryByIdDTO) {

        ResultVO<MemberDetailQuertResultDTO> result = ResultVO.success();
        Integer memberId = memberDetailQueryByIdDTO.getId();
        MhHuiyuan member = mhHuiyuanMapper.selectByPrimaryKey(memberId);
        if (EmptyUtil.isEmpty(member)) {
            return ResultVO.fail("无此用户ID");
        }
        MemberDetailQuertResultDTO memberDetailQuertResultDTO = new MemberDetailQuertResultDTO();
        BeanUtils.copyProperties(member, memberDetailQuertResultDTO);
        memberDetailQuertResultDTO.setShengyuyouhuicishu(getDiscounts(memberId));
        memberDetailQuertResultDTO.setDadanweiMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.DADANWEI, member.getDadanwei()));
        memberDetailQuertResultDTO.setZhijidaiyuMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.ZHIJIDAIYU, member.getZhijiedaiyu()));
        memberDetailQuertResultDTO.setZhuangtaiMingcheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.ZHUANGTAI, member.getZhuangtai()));
        result.setData(memberDetailQuertResultDTO);
        return result;
    }

    /**
     * 根据会员ID查询出该会员剩余的优惠次数
     *
     * @param huiyuanId
     * @return
     * @Author: ChenXiangpeng
     * @Date: 2019/8/1 18:02
     */
    private Integer getDiscounts(Integer huiyuanId) {
        List<MhHuiyuanQinshu> mhHuiyuanQinshus = mhHuiyuanQinshuMapper.selectByExample(Example.builder(MhHuiyuanQinshu.class).andWhere(
                Sqls.custom()
                        .andEqualTo("huiyuanId", huiyuanId)
                        .andEqualTo("guanxi", 0)
        ).build());
        if (null != mhHuiyuanQinshus && mhHuiyuanQinshus.size() == 1) {
            DiscountsRemainingQueryDTO discountsRemainingQueryDTO = new DiscountsRemainingQueryDTO();
            discountsRemainingQueryDTO.setContactIds(mhHuiyuanQinshus.get(0).getId());
            discountsRemainingQueryDTO.setRuzhushijian(new Date());
            ResultVO<Integer> remaining = reservationApi.remaining(discountsRemainingQueryDTO);
            return remaining.getData();
        }
        return null;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO userAdd(MemberAddDTO registerDTO) {
        ResultVO resultVO = ResultVO.fail();

        String redisLockKey = RedisConstants.HUIYUAN_ZHUCE_LOCK_KEY_PREFIX;
        try {
            String shenfenzhenghao = registerDTO.getShenfenzhenghao();
            shenfenzhenghao = CustomSecurity.encodeIDCard(shenfenzhenghao);

            //使用redis，根据酒店id对房间操作加锁
            redisLockKey = redisLockKey + shenfenzhenghao;
            boolean lockRet = commonRedisTemplate.opsForValue().setIfAbsent(redisLockKey, shenfenzhenghao);
            if (!lockRet) {
                log.error("系统繁忙，请重试");
                resultVO.setMessage("系统繁忙，请重试");
                return resultVO;
            }

            //验证身份证号是否重复
            QueryConditions andQueryConditions = new QueryConditions();
            andQueryConditions.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);

            QueryConditions orQueryConditions = new QueryConditions();
            orQueryConditions.addCondition("shenfenzhenghao", EConditionOperator.EQULS, shenfenzhenghao);
            orQueryConditions.addCondition("shoujihao", EConditionOperator.EQULS, encodeMobile(registerDTO.getShoujihao()));

            MyExample myExample = new MyExample(MhHuiyuan.class, andQueryConditions);
            Weekend weekend = myExample.createOrWeekend(MhHuiyuan.class, orQueryConditions);
            weekend.and(myExample.getOredCriteria().get(0));

            List<MhHuiyuan> huiyuanList = mhHuiyuanMapper.selectByExample(weekend);
            if (!CollectionUtils.isEmpty(huiyuanList)) {
                resultVO.setMessage("请勿重复添加");
                return resultVO;
            }

            //注册，针对huiyuan中的密码、手机号、身份证号，做加密处理
            MhHuiyuan huiyuan = new MhHuiyuan();
            BeanUtils.copyProperties(registerDTO, huiyuan);
            huiyuan.setZhuangtai(MhHuiyuan.ZHUANGTAI_YOUXIAO);
            huiyuan.setRenzhengzhuangtai(MhHuiyuan.RENZHENGZHUANGTAI_WEIRENZHENG);
            huiyuan.setYan(UUIDUtil.getUUID());
            String password = CustomSecurity.createUserPassword(shenfenzhenghao, huiyuan.getYan(), huiyuan.getMima());
            huiyuan.setMima(password);
            huiyuan.setShenfenzhenghao(shenfenzhenghao);
            huiyuan.setShoujihao(encodeMobile(huiyuan.getShoujihao()));
            huiyuan.setChuangjianshijian(new Date());
            huiyuan.setGengxinshijian(new Date());
            huiyuan.setShanchubiaoshi(SysDicConstant.DELFLAG_0);
            int ret = mhHuiyuanMapper.insertSelective(huiyuan);
            if (ret > 0) {
                resultVO.setCode(ResultVO.SUCCESS);
                resultVO.setMessage("用户添加成功");
            }

            //初始化联系人，插入自己
            ContactsAddInfoDto contactsAddInfoDto = new ContactsAddInfoDto();
            BeanUtils.copyProperties(registerDTO, contactsAddInfoDto);
            contactsAddInfoDto.setHuiyuanId(huiyuan.getId());
            contactsAddInfoDto.setGuanxi(MhHuiyuanQinshu.GUANXI_ZIJI);
            contactsAddInfoDto.setZhengjianleixing(MhHuiyuanQinshu.ZHENGJIANLEIXING_SHENFENZHENG);
            personalService.addContacts(contactsAddInfoDto);

        } catch (Exception e) {
            log.error("添加失败，系统异常", e);
            throw new BizException("添加失败，系统异常");
        } finally {
            commonRedisTemplate.delete(redisLockKey);
        }
        return resultVO;
    }

}
